home *** CD-ROM | disk | FTP | other *** search
/ Delphi Informant Complete 1995 - 2000 / Delphi Informant Complete 1995 to 2000.iso / Delphi Informant Magazine Complete Works SOURCE CODE 1998.rar / 1998 / Sep / di9809jp / BlastServer / SendMsg.pas < prev   
Pascal/Delphi Source File  |  1998-03-06  |  5KB  |  201 lines

  1. unit SendMsg;
  2.  
  3. interface
  4.  
  5. uses
  6.   Classes, Stdctrls, Windows, Winsock2;
  7.  
  8. const
  9.  
  10.  MaxAddrStr = 16;
  11.  
  12. type
  13.   TWorkMsg = array[0..MAXGETHOSTSTRUCT -1] of char;
  14.  
  15.   TMCOptions = record
  16.                 TTL,
  17.                 Port          : Integer;
  18.                 Address       : String;
  19.                end;
  20.  
  21.   TMultiCast = record
  22.                 imr_multiaddr : TInAddr;   // IP multicast address of group */
  23.                 imr_interface : TInAddr;   // local IP address of interface */
  24.                end;
  25.  
  26.   TSendMsgThrd = class(TThread)
  27.   private
  28.     { Private declarations }
  29.     Multicast  : TMultiCast;
  30.     Msg      : String;
  31.     Started  : Boolean;
  32.     wsaData  : TWSADATA;
  33.     sktBlast : TSocket;
  34.     LocalAddr,
  35.     RemoteAddr : TSockAddrIn;
  36.     LoopBackFlag : BOOL;
  37.     MCOptions  : TMCOptions;
  38.     Memo       : TMemo;
  39.     function  Start : Boolean;
  40.     procedure DisplayMsg;
  41.     procedure CleanUp(Sender : TObject);
  42.     procedure BlastMsg;
  43.     procedure Execute; override;
  44.   public
  45.    constructor Create(MsgMemo : TMemo; Options : TMCOptions);
  46.   end;
  47.  
  48.  
  49. var
  50.  SendMsgThrd : TSendMsgThrd;
  51.  
  52. implementation
  53.  
  54.  Uses
  55.   Main, SysUtils;
  56.  
  57.  const
  58.   WS2HighVersion = 2;
  59.   WS2LowVersion  = 2;
  60.  
  61.  
  62.  
  63.    function TSendMsgThrd.Start : Boolean;
  64.    var
  65.     VerReqd : WordRec;
  66.    begin
  67.     with VerReqd do
  68.     begin
  69.      Hi := WS2HighVersion;
  70.      Lo := WS2LowVersion;
  71.     end;
  72.     Result := WSAStartUp(Word(VerReqd), wsaData) = 0;
  73.    end;
  74.  
  75.    procedure TSendMsgThrd.DisplayMsg;
  76.    begin
  77.     frmMain.MemStatusMsg.Lines.Add(Msg);
  78.    end;
  79.  
  80.    procedure TSendMsgThrd.CleanUp(Sender : TObject);
  81.    begin
  82.     if Started then
  83.     begin
  84.      closesocket(sktBlast);
  85.      WSACleanUp;
  86.     end;
  87.    end;
  88.  
  89.    procedure TSendMsgThrd.BlastMsg;
  90.    var
  91.     Size : Byte;
  92.     sktRes : Integer;
  93.     WorkMsg : array[0..MAXGETHOSTSTRUCT-1] of char;
  94.     Buffer : PChar;
  95.    begin
  96.     with RemoteAddr do
  97.     begin
  98.      sin_family       := AF_INET;
  99.      sin_addr.s_addr  := inet_addr(pchar(MCOptions.Address));
  100.      sin_port         := htons(MCOptions.Port);
  101.     end;
  102.     Size             := Memo.GetTextLen;
  103.     Inc(Size);
  104.     Buffer := NIL;
  105.     try
  106.      GetMem(Buffer, Size);
  107.      Memo.GetTextBuf(WorkMsg,SizeOf(WorkMsg));
  108.      sktRes := sendto(sktBlast, WorkMsg, SizeOf(WorkMsg), 0, TSockAddrIn(RemoteAddr), SizeOf(RemoteAddr));
  109.      if sktRes = SOCKET_ERROR then
  110.      begin
  111.       Msg := Concat('Call to sendto failed! Error ', IntToStr(WSAGetLastError));
  112.       Synchronize(DisplayMsg);
  113.       closesocket(sktBlast);
  114.       Exit;
  115.      end;
  116.     finally
  117.      FreeMem(Buffer, Size);{Frees memory allocated to Buffer}
  118.     end;
  119.    end;
  120.  
  121.    constructor TSendMsgThrd.Create(MsgMemo : TMemo; Options : TMCOptions);
  122.    var
  123.     sktRes : Integer;
  124.    begin
  125.     inherited Create(TRUE);
  126.     FreeOnTerminate := TRUE;
  127.     OnTerminate := CleanUp;
  128.     Started := Start;
  129.     if not Started then
  130.     begin
  131.      Msg := 'Cannot load Winsock 2.0!';
  132.      Synchronize(DisplayMsg);
  133.      Exit;
  134.     end;
  135.     Memo := TMemo.Create(NIL);
  136.     Memo := MsgMemo;
  137.     MCOptions := Options;
  138.     sktBlast := socket(AF_INET, SOCK_DGRAM, 0);
  139.     if sktBlast = INVALID_SOCKET then
  140.     begin
  141.      Msg := Concat('Error creating datagram socket! Error ',IntToStr(WSAGetLastError));
  142.      Synchronize(DisplayMsg);
  143.      Exit;
  144.     end;
  145. // Bind the datagram socket
  146.     with LocalAddr do
  147.     begin
  148.      sin_family := AF_INET;
  149.      sin_addr.s_addr := htonl(INADDR_ANY); // any old interface
  150.      sin_port := 0;
  151.     end;
  152.     sktRes := bind(sktBlast,LocalAddr, SizeOf(TSockAddrIn));
  153.     if sktRes = SOCKET_ERROR then
  154.     begin
  155.      Msg := Concat('bind failed! Error ', IntToStr(WSAGetLastError));
  156.      Synchronize(DisplayMsg);
  157.      closesocket(sktRes);
  158.      Exit;
  159.     end;
  160. // Join the multicast group using setsockopt
  161.     with Multicast do
  162.     begin
  163.      imr_multiaddr.s_addr  := inet_addr(Pchar(MCOptions.Address));// IP multicast address of group *///MCAddrStr
  164.      imr_interface.s_addr  := INADDR_ANY;// local IP address of interface
  165.     end;
  166.     sktRes := setsockopt(sktBlast, IPPROTO_IP, IP_ADD_MEMBERSHIP, pchar(@multicast), SizeOf(multicast));
  167.     if sktRes = SOCKET_ERROR then
  168.     begin
  169.      Msg := Concat('setsockopt failed! Error ', IntToStr(WSAGetLastError));
  170.      Synchronize(DisplayMsg);
  171.      closesocket(sktBlast);
  172.      Exit;
  173.     end;
  174. // Set IP TTL by using setsockopt
  175.     sktRes := setsockopt(sktBlast, IPPROTO_IP, IP_MULTICAST_TTL, pchar(@MCOptions.TTL), SizeOf(MCOptions.TTL));
  176.     if sktRes = SOCKET_ERROR then
  177.     begin
  178.      Msg := Concat('setsockopt failed! Error ' + IntToStr(WSAGetLastError));
  179.      Synchronize(DisplayMsg);
  180.      closesocket(sktBlast);
  181.      Exit;
  182.     end;
  183. /// Disable loopback
  184.     LoopBackFlag := FALSE;
  185.     sktRes := setsockopt(sktBlast, IPPROTO_IP, IP_MULTICAST_LOOP, pchar(@LoopBackFlag), SizeOf(LoopBackFlag));
  186.     if sktRes = SOCKET_ERROR then
  187.     begin
  188.      Msg := Concat('Call to setsockopt failed! Error ', IntToStr(WSAGetLastError));
  189.      Synchronize(DisplayMsg);
  190.     end;
  191.     Resume;
  192.    end;
  193.  
  194.    procedure TSendMsgThrd.Execute;
  195.    begin
  196.    { Place thread code here }
  197.     BlastMsg;
  198.    end;
  199.  
  200. end.
  201.